#ifndef Algebra_SparseBlas_h
#define Algebra_SparseBlas_h

#include "AlgebraModule.h"
#include "AlgebraicTypes.h"
#include "Error.h"

SG_NAMESPACE_OPEN

namespace Algebra
{
    /**
     * @brief The sparse BLAS for several targeted sparse matrix/vector manipulations.
     *
     * In many applications (e.g., finite element methods) it is common to deal with
     * very large matrices where only a few coefficients are different from zero.
     * In such cases, memory consumption can be reduced and performance increased
     * by using a specialized representation storing only the nonzero coefficients.
     *
     * @see https://eigen.tuxfamily.org/dox/group__TutorialSparse.html
     *
     * BLAS stands for Basic Linear Algebra Subprograms. BLAS provides standard interfaces
     * for linear algebra, including BLAS1 (vector-vector operations), BLAS2 (matrix-vectoroperations),
     * and BLAS3 (matrix-matrix operations). In general, BLAS is the computational kernel
     * ("the bottom of the food chain") in linear algebra or scientific applications.
     *
     * OpenBLAS implements only the standard (dense) BLAS and LAPACK functions with a select
     * few extensions popularized by Intel's MKL. Some cases can probably be made to work using
     * e.g. GEMV or AXPBY, in general using a dedicated package like SuiteSparse (which can make
     * use of OpenBLAS or equivalent for standard operations) is recommended.
     *
     * @see https://github.com/OpenMathLib/OpenBLAS
     *
     * The Sparse BLAS Level 1 Routines and Functions and Sparse BLAS Level 2 and Level 3 routines
     * and functions operate on sparse vectors and matrices. These routines perform vector operations
     * similar to the BLAS Level 1, 2, and 3 routines. The Sparse BLAS routines take advantage of
     * vector and matrix sparsity: they allow you to store only non-zero elements of vectors and matrices.
     * 
     * @see https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2024-2/overview-001.html
     *
     * @author nene
     * @date September, 2024.
     */
    class ALGEBRA_EXPORT SparseBlas
    {
    public:
        SparseBlas ();
        ~SparseBlas ();

        /**
         * Inserts or adds a block of values into a matrix.
         * The block will be inserted in location (StartRow, StartCol).
         * @note Compressed Column Storage scheme Assumed.
         */
        static Info_t setValues (ComplexSpMat_t& A, const Int_t& StartRow, const Int_t& StartCol, const SpMat_t& Aij);

        /// Computes a vector-vector dot product.
        static Info_t dot (const Vec_t& X, const Vec_t& Y, Real_t& R);

        /// Computes a complex vector-vector dot product.
        static Info_t dot (const ComplexVec_t& X, const ComplexVec_t& Y, Complex_t& R);

        /**
         * Compute matrix-vector product for a sparse matrix in the CSC format.
         * In order to optimize the performance, take the result as an additional argument.
         */
        static Info_t multiply (const SpMat_t& A, Vec_t& X, Vec_t& Y);

        static Info_t multiply (const ComplexSpMat_t& A, ComplexVec_t& X, ComplexVec_t& Y);
    };

}  // namespace Algebra

SG_NAMESPACE_CLOSE

#endif  // Algebra_SparseBlas_h